Differenza tra decimale, float e double in .NET?
-
03-07-2019 - |
Domanda
Qual è la differenza tra decimale
, float
e double
in .NET?
Quando qualcuno userebbe uno di questi?
Soluzione
float
e double
sono floating < em> binario tipi di punti . In altre parole, rappresentano un numero come questo:
10001.10010110011
Il numero binario e la posizione del punto binario sono entrambi codificati all'interno del valore.
decimal
è un decimale mobile digitare . In altre parole, rappresentano un numero come questo:
12345.65789
Ancora una volta, il numero e la posizione del punto decimale sono entrambi codificati all'interno del valore & # 8211; questo è ciò che rende decimale
ancora un tipo a virgola mobile anziché un tipo a virgola fissa.
La cosa importante da notare è che gli umani sono abituati a rappresentare numeri non interi in forma decimale e si aspettano risultati esatti in rappresentazioni decimali; non tutti i numeri decimali sono esattamente rappresentabili in virgola mobile binaria & # 8211; 0.1, ad esempio & # 8211; quindi se usi un valore binario in virgola mobile otterrai effettivamente un'approssimazione a 0,1. Otterrai comunque approssimazioni anche quando utilizzi un punto decimale mobile & # 8211; il risultato della divisione 1 per 3 non può essere rappresentato esattamente, per esempio.
Per quanto riguarda cosa usare quando:
-
Per valori che sono "naturalmente decimali esatti" è bene usare
decimale
. Questo di solito è adatto a qualsiasi concetto inventato dall'uomo: i valori finanziari sono l'esempio più ovvio, ma ce ne sono anche altri. Considera il punteggio assegnato ai sub o ai pattinatori su ghiaccio, ad esempio. -
Per valori che sono più artefatti della natura che non possono essere realmente misurati esattamente comunque,
float
/double
sono più adeguata. Ad esempio, i dati scientifici sarebbero di solito rappresentati in questo modulo. Qui, i valori originali non saranno "accuratamente decimali" per cominciare, quindi non è importante che i risultati previsti mantengano la "precisione decimale". I tipi di punti binari mobili sono molto più veloci con i decimali.
Altri suggerimenti
La precisione è la differenza principale.
Float - 7 cifre (32 bit)
Double -15-16 cifre (64 bit)
Decimal -28-29 cifre significative (128 bit )
I decimali hanno una precisione molto più elevata e vengono generalmente utilizzati in applicazioni finanziarie che richiedono un elevato grado di accuratezza. I decimali sono molto più lenti (fino a 20 volte volte in alcuni test) rispetto a un doppio / float.
I decimali e i float / i doppi non possono essere confrontati senza un cast, mentre i float e i doppi possono farlo. I decimali consentono anche la codifica o gli zeri finali.
float flt = 1F/3;
double dbl = 1D/3;
decimal dcm = 1M/3;
Console.WriteLine("float: {0} double: {1} decimal: {2}", flt, dbl, dcm);
Risultato:
float: 0.3333333
double: 0.333333333333333
decimal: 0.3333333333333333333333333333
La struttura decimale è strettamente orientata ai calcoli finanziari che richiedono precisione, che sono relativamente intolleranti all'arrotondamento. I decimali non sono adeguati per le applicazioni scientifiche, tuttavia, per diversi motivi:
- Una certa perdita di precisione è accettabile in molti calcoli scientifici a causa dei limiti pratici del problema fisico o artefatto da misurare. La perdita di precisione non è accettabile in ambito finanziario.
- Il decimale è molto (molto) più lento del float e del doppio per la maggior parte delle operazioni, principalmente perché le operazioni in virgola mobile vengono eseguite in binario, mentre le cose decimali vengono eseguite in base 10 (ovvero float e double sono gestiti dall'hardware FPU, come MMX / SSE, mentre i decimali sono calcolati nel software).
- Il decimale ha un intervallo di valori inaccettabilmente inferiore rispetto al doppio, nonostante supporti più cifre di precisione. Pertanto, Decimal non può essere utilizzato per rappresentare molti valori scientifici.
+---------+----------------+---------+----------+---------------------------------------------+
| C# | .Net Framework | Signed? | Bytes | Possible Values |
| Type | (System) type | | Occupied | |
+---------+----------------+---------+----------+---------------------------------------------+
| sbyte | System.Sbyte | Yes | 1 | -128 to 127 |
| short | System.Int16 | Yes | 2 | -32768 to 32767 |
| int | System.Int32 | Yes | 4 | -2147483648 to 2147483647 |
| long | System.Int64 | Yes | 8 | -9223372036854775808 to 9223372036854775807 |
| byte | System.Byte | No | 1 | 0 to 255 |
| ushort | System.Uint16 | No | 2 | 0 to 65535 |
| uint | System.UInt32 | No | 4 | 0 to 4294967295 |
| ulong | System.Uint64 | No | 8 | 0 to 18446744073709551615 |
| float | System.Single | Yes | 4 | Approximately ±1.5 x 10-45 to ±3.4 x 1038 |
| | | | | with 7 significant figures |
| double | System.Double | Yes | 8 | Approximately ±5.0 x 10-324 to ±1.7 x 10308 |
| | | | | with 15 or 16 significant figures |
| decimal | System.Decimal | Yes | 12 | Approximately ±1.0 x 10-28 to ±7.9 x 1028 |
| | | | | with 28 or 29 significant figures |
| char | System.Char | N/A | 2 | Any Unicode character (16 bit) |
| bool | System.Boolean | N/A | 1 / 2 | true or false |
+---------+----------------+---------+----------+---------------------------------------------+
Per ulteriori informazioni, consultare:
http: //social.msdn .microsoft.com / Forum / it-IT / csharpgeneral / thread / 921a8ffc-9829-4145-bdc9-a96c1ec174a5
float
7 cifre di precisione
double
ha circa 15 cifre di precisione
decimale
ha circa 28 cifre di precisione
Se hai bisogno di una maggiore precisione, usa double invece di float. Nelle CPU moderne entrambi i tipi di dati hanno quasi le stesse prestazioni. L'unico vantaggio dell'utilizzo di float è che occupano meno spazio. Praticamente conta solo se ne hai molti.
Ho trovato questo interessante. Ciò che ogni scienziato informatico dovrebbe sapere sull'aritmetica a virgola mobile
Non ripeterò tonnellate di informazioni buone (e alcune cattive) che hanno già risposto in altre risposte e commenti, ma risponderò alla tua domanda di follow-up con un suggerimento:
Quando qualcuno dovrebbe usare uno di questi?
Usa i decimali per contati valori
Usa float / double per valori misurati
Alcuni esempi:
-
denaro (contiamo i soldi o misuriamo i soldi?)
-
distanza (contiamo la distanza o misuriamo la distanza? *)
-
punteggi (contiamo i punteggi o misuriamo i punteggi?)
Contiamo sempre il denaro e non dovremmo mai misurarlo. Di solito misuriamo la distanza. Contiamo spesso i punteggi.
* In alcuni casi, ciò che definirei distanza nominale , potremmo davvero voler "contare" la distanza. Ad esempio, forse abbiamo a che fare con segni di paesi che mostrano le distanze dalle città e sappiamo che tali distanze non hanno mai più di una cifra decimale (xxx.x km).
Nessuno lo ha menzionato
Nelle impostazioni predefinite, Floats (System.Single) e doppi (System.Double) non verranno mai utilizzati controllo di overflow mentre Decimal (System.Decimal) utilizzerà sempre controllo di overflow.
Intendo
decimal myNumber = decimal.MaxValue;
myNumber += 1;
genera OverflowException .
Ma questi non lo fanno:
float myNumber = float.MaxValue;
myNumber += 1;
& amp;
double myNumber = double.MaxValue;
myNumber += 1;
I numeri interi, come detto, sono numeri interi. Non possono memorizzare il punto qualcosa, come .7, .42 e .007. Se è necessario memorizzare numeri che non sono numeri interi, è necessario un diverso tipo di variabile. È possibile utilizzare il tipo doppio o il tipo float. Puoi impostare questi tipi di variabili esattamente nello stesso modo: invece di usare la parola int
, digiti double
o float
. In questo modo:
float myFloat;
double myDouble;
( float
è l'abbreviazione di " virgola mobile " ;, e significa solo un numero con un punto qualcosa alla fine.)
La differenza tra i due sta nella dimensione dei numeri che possono contenere. Per float
, puoi avere fino a 7 cifre nel tuo numero. Per double
, puoi avere fino a 16 cifre. Per essere più precisi, ecco la dimensione ufficiale:
float: 1.5 × 10^-45 to 3.4 × 10^38
double: 5.0 × 10^-324 to 1.7 × 10^308
float
è un numero a 32 bit e double
è un numero a 64 bit.
Fai doppio clic sul tuo nuovo pulsante per accedere al codice. Aggiungi le seguenti tre righe al codice del pulsante:
double myDouble;
myDouble = 0.007;
MessageBox.Show(myDouble.ToString());
Arresta il programma e torna alla finestra di codifica. Cambia questa riga:
myDouble = 0.007;
myDouble = 12345678.1234567;
Esegui il programma e fai clic sul doppio pulsante. La finestra di messaggio visualizza correttamente il numero. Aggiungi un altro numero alla fine, tuttavia, e C # tornerà di nuovo in alto o in basso. La morale è se vuoi precisione, fai attenzione a arrotondare!
- Double e float possono essere divisi per lo zero intero senza eccezioni sia durante la compilazione che durante l'esecuzione.
- Il decimale non può essere diviso per lo zero intero. La compilazione fallirà sempre se lo fai.
Questo è stato un thread interessante per me, dato che oggi abbiamo appena avuto un piccolo bug per quanto riguarda decimale
che ha meno precisione di un float
.
Nel nostro codice C #, stiamo leggendo valori numerici da un foglio di calcolo Excel, convertendoli in un decimale
, quindi inviando questo decimale
a un servizio per salvarlo in un database SQL Server .
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
decimal value = 0;
Decimal.TryParse(cellValue.ToString(), out value);
}
Ora, per quasi tutti dei nostri valori di Excel, ha funzionato magnificamente. Ma per alcuni valori di Excel molto piccoli, l'utilizzo di decimal. TryParse
ha perso completamente il valore. Uno di questi esempi è
-
cellValue = 0.00006317592
Decimal.TryParse (cellValue.ToString (), out value); // restituisce 0
La soluzione, stranamente, era convertire prima i valori di Excel in un double
, quindi in un decimale
:
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
double valueDouble = 0;
double.TryParse(cellValue.ToString(), out valueDouble);
decimal value = (decimal) valueDouble;
…
}
Anche se double
ha meno precisione di un decimale
, questo ha garantito che i piccoli numeri sarebbero stati comunque riconosciuti. Per qualche motivo, double.TryParse
è stato effettivamente in grado di recuperare numeri così piccoli, mentre decimal. TryParse
avrebbe impostato a zero.
Odd. Molto strano.
- float: & # 177; 1,5 x 10 ^ -45 a & # 177; 3,4 x 10 ^ 38 (~ 7 cifre significative
- doppio: & # 177; 5,0 x 10 ^ da -324 a & # 177; 1,7 x 10 ^ 308 (15-16 cifre significative)
- decimale: & # 177; 1,0 x 10 ^ -28 a & # 177; 7,9 x 10 ^ 28 (28-29 cifre significative)
Per applicazioni come giochi e sistemi embedded in cui memoria e prestazioni sono entrambi fondamentali, il float è di solito il tipo numerico di scelta in quanto è più veloce e la metà delle dimensioni di un doppio. I numeri interi erano l'arma preferita, ma le prestazioni in virgola mobile hanno superato i numeri interi nei processori moderni. Decimale è subito!
I tipi di variabile Decimale, Doppio e Float sono diversi nel modo in cui memorizzano i valori. La precisione è la principale differenza in cui float è un tipo di dati a virgola mobile a precisione singola (32 bit), double è un tipo di dati a virgola mobile a precisione doppia (64 bit) e decimale è un tipo di dati a virgola mobile a 128 bit.
Float - 32 bit (7 cifre)
Doppia - 64 bit (15-16 cifre)
Decimale - 128 bit (28-29 cifre significative)
Ulteriori informazioni su ... la differenza tra Decimale, Float e Doppio
Il problema con tutti questi tipi è che sussiste una certa imprecisione E che questo problema può verificarsi con piccoli numeri decimali come nell'esempio seguente
Dim fMean as Double = 1.18
Dim fDelta as Double = 0.08
Dim fLimit as Double = 1.1
If fMean - fDelta < fLimit Then
bLower = True
Else
bLower = False
End If
Domanda: quale valore contiene la variabile bLower?
Risposta: su una macchina a 32 bit bLower contiene TRUE !!!
Se sostituisco Double con Decimal, bLower contiene FALSE che è la buona risposta.
In doppio, il problema è che fMean-fDelta = 1.09999999999 che è inferiore a 1.1.
Attenzione: penso che lo stesso problema possa certamente esistere per un altro numero perché Decimal è solo un doppio con una precisione maggiore e la precisione ha sempre un limite.
In effetti, Double, Float e Decimal corrispondono al decimale BINARY in COBOL!
È deplorevole che altri tipi numerici implementati in COBOL non esistano in .Net. Per coloro che non conoscono COBOL, esistono COBOL che seguono il tipo numerico
BINARY or COMP like float or double or decimal
PACKED-DECIMAL or COMP-3 (2 digit in 1 byte)
ZONED-DECIMAL (1 digit in 1 byte)
In parole semplici:
- I tipi di variabile Decimale, Doppio e Float sono diversi nel modo in cui memorizzano i valori.
- La precisione è la differenza principale (si noti che questa non è la singola differenza) dove float è una precisione singola (32 bit) mobile tipo di dati in virgola mobile, doppio è un tipo di dati in virgola mobile a precisione doppia (64 bit) e decimale è un tipo di dati in virgola mobile a 128 bit.
- La tabella di riepilogo:
/==========================================================================================
Type Bits Have up to Approximate Range
/==========================================================================================
float 32 7 digits -3.4 × 10 ^ (38) to +3.4 × 10 ^ (38)
double 64 15-16 digits ±5.0 × 10 ^ (-324) to ±1.7 × 10 ^ (308)
decimal 128 28-29 significant digits ±7.9 x 10 ^ (28) or (1 to 10 ^ (28)
/==========================================================================================
Puoi leggere di più qui , Float , Double e Decimale .
La principale differenza tra ciascuno di questi è la precisione.
float
è un 32-bit
, double
è un 64-bit
e decimale
è un numero 128-bit
.